<?php

namespace app\tools;

use app\model\Common;
use PHPQRCode\QRcode;
use think\cache\driver\Redis;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

/**
 * 微信公众平台API接口
 *
 * Class Wx
 * @package projects\tools
 */
class WxPlatform
{

    /**
     * 公众号请求地址
     * User : Du
     * Date : 2022/11/22
     * Time : 22:23
     * @var string
     */
    private static string $apiUrl = 'https://api.weixin.qq.com/cgi-bin/';

    /**
     * 扫码绑定地址
     * User : Du
     * Date : 2022/11/23
     * Time : 14:40
     * @var string
     */
    private static string $oauthUrl = 'https://open.weixin.qq.com/connect/oauth2/';

    /**
     * 获取用户信息地址
     * User : Du
     * Date : 2022/11/23
     * Time : 14:41
     * @var string
     */
    private static string $snsUrl = 'https://api.weixin.qq.com/sns/';


    /**
     * 获取公众号token
     * User : Du
     * Date : 2022/11/22
     * Time : 22:23
     * @return string
     */
    public static function getAccessToken(): string
    {
        $redis = new Redis();
//        if (!$token = $redis->get('wx_assess_token')) {
        $appid = env('wx.appid');
        $secret = env('wx.appsecret');
        $url = self::$apiUrl . 'token?grant_type=client_credential&appid=' . $appid . '&secret=' . $secret;
        $res = curl($url);
        if (!isset($res['access_token'])) {
            return false;
        }
        $redis->set('wx_assess_token', $res['access_token'], 7000);
        $token = $res['access_token'];
//        }
        return $token;
    }

    /**
     * 获取微信ticket并生成二维码图片
     * User : Du
     * Date : 2022/11/22
     * Time : 22:23
     * @param string $token
     * @param string $type
     * @return array
     * @throws DbException
     */
    public static function getTicket(string $token, string $type): array
    {
        $id = Common::addData(WxQrTable, ['type' => $type], true);
        $data = [
            'expire_seconds' => 300,
            'action_name' => 'QR_SCENE',
            'action_info' => [
                'scene' => [
                    'scene_id' => $id,
                ]
            ],
        ];
        $url = self::$apiUrl . 'qrcode/create?access_token=' . $token;
        $res = curl($url, $data);
        if (!isset($res['ticket'])) {
            return [];
        }
        Common::updateData(WxQrTable, ['id' => $id], ['ticket' => $res['ticket']]);
        return [
            'id' => $id,
            'url' => 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=' . urlencode($res['ticket'])
        ];
    }

    /**
     * 获取该微信绑定的用户
     * User : Du
     * Date : 2022/11/22
     * Time : 22:23
     * @param array $request
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function getBingUser(array $request): void
    {
        $field = ['id', 'admin_id', 'type', 'status'];
        $log = Common::getData(AdminWxLogTable, ['ticket' => $request['Ticket']], $field);
        switch ($log['type']) {
            case 1:  //登录
                $res = Common::getData(AdminTable, ['wx_openid' => $request['FromUserName']], ['id', 'status']);
                if (!$res) {
                    $data = ['status' => 10];
                } else {
                    if ($res['status'] === 2) {  //禁用
                        $data = ['status' => 11];
                    } else {
                        $data = [
                            'admin_id' => $res['id'],
                            'status' => 1,
                        ];
                    }
                }
                Common::updateData(AdminWxLogTable, ['id' => $log['id']], $data);
                break;
            case 2:  //绑定
                $res = Common::getValue(AdminTable, ['wx_openid' => $request['FromUserName']], 'id');
                if (!$res) {
                    Common::updateData(AdminTable, ['id' => $log['admin_id']], ['wx_openid' => $request['FromUserName']]);
                    Common::updateData(AdminWxLogTable, ['id' => $log['id']], ['status' => 1]);
                } else {
                    Common::updateData(AdminWxLogTable, ['id' => $log['id']], ['status' => 2]);
                }
                break;
            default:
                Common::updateData(AdminWxLogTable, ['id' => $log['id']], ['status' => 5]);  //失败
        }
    }

    /**
     * 根据openid获取用户信息---微信已废弃该API
     * User : Du
     * Date : 2022/11/22
     * Time : 22:23
     * @param string $openid
     * @return false
     */
    public static function getUserInfo(string $openid): bool
    {
//        $token = self::getAccessToken();
//        if (!$token) {
//            return false;
//        }
//        $url = self::$apiUrl . 'user/info?access_token=' . $token . '&openid=' . $openid . '&lang=zh_CN';
//
//        $res = curl($url);
//        Logs::info('获取用户信息', ['data' => $res], 'userInfo');
    }

    /**
     * 微信绑定url
     * User : Du
     * Date : 2022/11/22
     * Time : 22:50
     * @param int $id
     * @return string
     */
    public static function getBindUrl(int $id): string
    {
        $appid = env('wx.appid');
        $callbackdomain = env('wx.callbackdomain');
        $callbackUrl = urlencode($callbackdomain);
        $url = self::$oauthUrl .
            'authorize?appid=' . $appid .
            '&redirect_uri=' . $callbackUrl .
            '&response_type=code' .
            '&scope=snsapi_userinfo' .
            '&state=' . $id .
            '#wechat_redirect';
        //生成png图片转换成base64
        ob_start();
        QRcode::png($url);
        $imgString = base64_encode(ob_get_contents());
        ob_end_clean();
        return "data:imgage/jpe;base64," . $imgString;
    }

    /**
     * 用户绑定账号回调
     * User : Du
     * Date : 2022/11/23
     * Time : 15:13
     * @param array $data
     * @return bool|string
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function userCode(array $data)
    {
        $appid = env('wx.appid');
        $secret = env('wx.appsecret');
//        $data = [
//            'code' => '0619yuFa17GeiE0xSSHa1OwWVa49yuF4',
//            'state' => 1,
//        ];
        $tokenUrl = self::$snsUrl . 'oauth2/access_token?' .
            'appid=' . $appid .
            '&secret=' . $secret .
            '&code=' . $data['code'] .
            '&grant_type=authorization_code';
        $res = curl($tokenUrl);
        if (!isset($res['access_token'])) {  //获取token失败
            Logs::error('用户绑定获取token错误', ['data' => $res], 'wxUserCode');
            return '获取信息失败，配置错误';
        }
        $user = Common::getData(UserTable, ['wx_openid' => $res['openid']], ['id']);
        if ($user) {  //该微信已绑定其他账号
            Common::updateData(WxQrTable, ['id' => $data['state']], ['status' => 4]);
            return '该微信已绑定其他账号';
        }
        $userInfoUrl = self::$snsUrl . 'userinfo?access_token=' . $res['access_token'] . '&openid=' . $res['openid'] . '&lang=zh_CN';
        $userInfo = curl($userInfoUrl);
        if (isset($userInfo['errcode'])) {
            Logs::error('获取微信用户信息错误', ['data' => $res], 'wxUserCode');
            Common::updateData(WxQrTable, ['id' => $data['state']], ['status' => 5]);
            return '获取用户信息失败';
        }
        //已获取用户信息
        $userid = Common::getValue(WxQrTable, ['id' => $data['state']], 'user_id');
        Common::updateData(UserTable, ['id' => $userid], ['wx_openid' => $userInfo['openid'], 'wx_name' => $userInfo['nickname']]);
        Common::updateData(WxQrTable, ['id' => $data['state']], ['status' => 3]);
        $userInfo['privilege'] = arrayToJson($userInfo['privilege']);
        $userInfo['user_id'] = $userid;
        Common::addData(UserWxTable, $userInfo);
        return true;
    }

    /**
     * 获取带参数的临时二维码
     * 网址： https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html
     */
    public static function getWxtTicketUrl(int $id)
    {
        $token = self::getAccessToken();
        if (!$token) {
            return false;
        }
        $url = self::$apiUrl . 'qrcode/create?access_token=' . $token;
        $data = [
            'expire_seconds' => 300,  //二维码过期时间
            'action_name' => 'QR_SCENE',  //临时数字参数
            'action_info' => [
                'scene' => [
                    'scene_id' => $id,
                ]
            ],
        ];
        $res = curl($url, $data);
        if (isset($res['ticket']) && $res['expire_seconds']) {
            //获取成功
            return [
                'ticket' => $res['ticket'],
                'url' => 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=' . urlencode($res['ticket']),
            ];
        }
        return false;
    }
}
